﻿using System.Reflection;
using System.Text;

namespace ShadowCode;

public abstract partial class GeneratorBase : IIncrementalGenerator
{
    protected const StringSplitOptions RemoveEmptyEntries = StringSplitOptions.RemoveEmptyEntries;
    protected readonly static AssemblyName assembly = typeof(GeneratorBase).Assembly.GetName();
    protected readonly static string assemblyName = assembly.Name ?? "未知";
    protected readonly static string version = $"{assembly.Name} {assembly.Version}";

    protected int index;

    public void Initialize(IncrementalGeneratorInitializationContext context)
    {
        // Debugger.Launch();
        context.RegisterPostInitializationOutput(RegisterPostInitializationOutput);

        var collect = GetCollects(context).Collect();
        var data = context.CompilationProvider
            .Combine(context.AnalyzerConfigOptionsProvider)
            .Combine(collect);

        context.RegisterImplementationSourceOutput(data, (context, r) =>
        {
            var start = DateTime.Now;
            Interlocked.Increment(ref index);
            var compilation = r.Left.Left;
            var options = r.Left.Right;
            var array = r.Right;
            AnalyzerConfigHandler(options);
            Build(context, compilation, array, start);
            AddConfigCode(context);

#if DEBUG           
            Log($"ImplementationSourceOutput : [{index}], {DateTime.Now}");
#endif
        });
    }

    protected virtual void AddConfigCode(SourceProductionContext context)
    {
        var sb = new StringBuilder();
        InitConfigCollect(sb);
        context.AddSource("ShadowCode.Config.cs", $"""
        /* 
        {sb}
        */
        """);
    }


    protected abstract void Build(SourceProductionContext context,
        Compilation compilation, ImmutableArray<TransformData> array, DateTime start);

    protected abstract IncrementalValuesProvider<TransformData> GetCollects(IncrementalGeneratorInitializationContext context);

    protected virtual void RegisterPostInitializationOutput(
        IncrementalGeneratorPostInitializationContext context)
    { }

    protected virtual void AnalyzerConfigHandler(AnalyzerConfigOptionsProvider options)
    { }

    protected virtual void Log(string value)
    { }

    protected virtual void InitConfigCollect(StringBuilder config)
    { }
}
